package cn.javasea.rbac.shiro.shiro;

import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.util.ThreadContext;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @Description: shiro核心配置类
 * @Author: xiangchao
 * @Date: 2023/2/1
 */
@Configuration
public class ShiroConfig {

    /**
     * 拦截器配置
     * @author xiangchao
     * @date 2023/2/1 19:04
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        //设置安全管理器
        bean.setSecurityManager(securityManager);
        // 添加自己的过滤器并且取名为jwt
        LinkedHashMap<String, Filter> filterMap = new LinkedHashMap<>();
        filterMap.put("myFilter", new ShiroFilter());
        bean.setFilters(filterMap);
        //添加shiro的内置过滤器
        Map<String, String> filterChainMap = new LinkedHashMap<>();
        // 过滤链定义，从上向下顺序执行，一般将放在最为下边
        filterChainMap.put("/login", "anon");
        filterChainMap.put("/targetUrl", "myFilter");
        filterChainMap.put("/scmp-manage/targetUrl", "myFilter");
        filterChainMap.put("/**", "authc");
        bean.setFilterChainDefinitionMap(filterChainMap);
        return bean;
    }

    public ShiroFilter shiroFilter(){
        return new ShiroFilter();
    }

    @Bean
    public RedisCacheManager redisCacheManager(@Qualifier("redisManager") RedisManager redisManager) {
        RedisCacheManager redisCacheManager = new RedisCacheManager();
        redisCacheManager.setRedisManager(redisManager);
        return redisCacheManager;
    }

    /**
     * 配置shiro redisManager
     *
     * @return
     */
    @Bean
    public RedisManager redisManager() {
        RedisManager redisManager = new RedisManager();
        redisManager.setHost("127.0.0.1");
        redisManager.setPort(6379);
        return redisManager;
    }

    @Bean
    public RedisSessionDAO redisSessionDAO(@Qualifier("redisManager") RedisManager redisManager) {
        RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
        redisSessionDAO.setRedisManager(redisManager);
        return redisSessionDAO;
    }

    /**
     * 集成用户认证和授权模块
     * @author xiangchao
     * @date 2023/2/1 19:04
     */
    @Bean
    public DefaultWebSecurityManager securityManager(@Qualifier("shiroRealm") ShiroRealm shiroRealm,
                                                     @Qualifier("redisCacheManager") RedisCacheManager redisCacheManager,
                                                     DefaultWebSessionManager defaultWebSessionManager) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // session管理器
        securityManager.setSessionManager(defaultWebSessionManager);
        // 设置redis的key有效时间
        redisCacheManager.setExpire(999999999);
        // 自定义缓存实现 使用redis
        //securityManager.setCacheManager(redisCacheManager);
        securityManager.setRealm(shiroRealm);
        ThreadContext.bind(securityManager);
        return securityManager;
    }

    @Bean
    public ShiroRealm shiroRealm(){
        return new ShiroRealm();
    }

    /**
     * shiro session的管理
     */
    @Bean
    public DefaultWebSessionManager sessionManager(@Qualifier("redisSessionDAO") RedisSessionDAO redisSessionDAO) {
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        //sessionManager.setSessionDAO(redisSessionDAO);
        return sessionManager;
    }

    /**
     * 开启aop注解支持
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

}
